
#include <BPainter>
#include <BWidget>
#include <BMouseEvent>
#include <BVBoxLayout>
#include "member_BVBoxLayout.h"
#include "member_BWidget.h"
#include "member_BLayout.h"
#include "member_BSpacer.h"
#include "member_BSpring.h"
#include "member_BStyle.h"

using namespace BWE;

#define member					(*(member_BVBoxLayout*)_ptr)
#define member_allocate()		_ptr = new member_BVBoxLayout(this)
#define member_release()		delete (member_BVBoxLayout*)_ptr

BVBoxLayout::BVBoxLayout(BWidget* host) : BLayout(host)
{
	member_allocate();
}
BVBoxLayout::BVBoxLayout(BWidget* host, PartFlag part) : BLayout(host, part)
{
	member_allocate();
}
BVBoxLayout::BVBoxLayout(const BString& name, BWidget* host) : BLayout(name, host)
{
	member_allocate();
}
BVBoxLayout::BVBoxLayout(Policy widthPolicy, Policy heightPolicy, BWidget* host) : BLayout(host)
{
	member_allocate();
	this->setSizePolicy(BSizePolicy(widthPolicy, heightPolicy));
}
BVBoxLayout::~BVBoxLayout()
{
	clear();
	member_release();
}

void BVBoxLayout::setSpacing(int spacing)
{
	if (member.spacing != spacing)
	{
		member.spacing = spacing;
		this->emit(Signal_SpacingChanged, spacing);
		BLayout::dirty();
	}
}
int BVBoxLayout::spacing() const
{
	return member.spacing;
}

void BVBoxLayout::setHandleSize(const BSize& handleSize)
{
	if (member.handleSize != handleSize)
	{
		member.handleSize = handleSize;
		this->fresh();
	}
}
const BSize& BVBoxLayout::handleSize() const
{
	return member.handleSize;
}

void BVBoxLayout::setSplitable(bool splitable)
{
	if (member.splitable != splitable)
	{
		member.splitable = splitable;
		BLayout::dirty();
	}
}
bool BVBoxLayout::splitable() const
{
	return member.splitable;
}

bool BVBoxLayout::setAlign(int pos, Align align)
{
	if (member.items.check(pos))
		return false;
	ILayoutItem& item = member.items[pos];
	if (item.align != align)
	{
		item.align = align;
		BLayout::dirty();
	}
	return true;
}
Align BVBoxLayout::align(int pos) const
{
	return member.items(pos).align;
}

bool BVBoxLayout::setAlign(BObject* object, Align align)
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item != object)
			continue;
		if (item.align != align)
		{
			item.align = align;
			BLayout::dirty();
		}
		return true;
	}
	return false;
}
Align BVBoxLayout::align(BObject* object) const
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item != object)
			continue;
		return item.align;
	}
	return Align_None;
}

bool BVBoxLayout::setStretch(int pos, float stretch)
{
	if (member.items.size() < pos + 1)
	{
		int size = 1 + pos - member.items.size();
		member.items.append(ILayoutItem(), size);
	}
	ILayoutItem& item = member.items[pos];
	if (item.stretch.heightStretch() != stretch)
	{
		item.stretch.heightStretch() = stretch;
		BLayout::dirty();
	}
	return true;
}
float BVBoxLayout::stretch(int pos) const
{
	return member.items(pos).stretch.heightStretch();
}

bool BVBoxLayout::setStretch(BObject* object, float stretch)
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item != object)
			continue;
		if (item.stretch != stretch)
		{
			item.stretch.heightStretch() = stretch;
			BLayout::dirty();
		}
		return true;
	}
	return false;
}
float BVBoxLayout::stretch(BObject* object) const
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item != object)
			continue;
		return item.stretch.heightStretch();
	}
	return 0.0f;
}

bool BVBoxLayout::addWidget(BWidget* widget, float stretch)
{
	if (!widget)
		return false;
	if (this->host() == widget)
		return false;
	if (widget_member(widget)->upperLayout == this)
		return true;
	member.items.append(ILayoutItem());
	ILayoutItem& item = member.items.last();
	item.widget = widget;
	if (stretch >= 0.0f)
		item.stretch.heightStretch() = stretch;
	if (widget_member(widget)->upperLayout)
		widget_member(widget)->upperLayout->remove(widget);
	widget_member(widget)->upperLayout = this;
	if (layout_member(this)->host)
		layout_member(this)->host->addChild(widget);
	BLayout::dirty();
	return true;
}
bool BVBoxLayout::addLayout(BLayout* layout, float stretch)
{
	if (!layout || layout == this)
		return false;
	if (!member.items.append(ILayoutItem()))
		return false;
	ILayoutItem& item = member.items.last();
	item.layout = layout;
	if (stretch >= 0.0f)
		item.stretch.heightStretch() = stretch;
	if (layout_member(layout)->parent)
		layout_member(layout)->parent->remove(layout);
	layout_member(layout)->parent = this;
	layout_member(layout)->setHost(layout_member(this)->host);
	BLayout::dirty();
	return true;
}
bool BVBoxLayout::addSpacer(BSpacer* spacer, float stretch)
{
	if (!spacer)
		return false;
	if (spacer_member(spacer)->layout == this)
		return true;
	if (!member.items.append(ILayoutItem()))
		return false;
	ILayoutItem& item = member.items.last();
	item.spacer = spacer;
	if (stretch >= 0.0f)
		item.stretch.heightStretch() = stretch;
	if (spacer_member(spacer)->layout)
		spacer_member(spacer)->layout->remove(spacer);
	spacer_member(spacer)->layout = this;
	BLayout::dirty();
	return true;
}
bool BVBoxLayout::addSpring(BSpring* spring, float stretch)
{
	if (!spring)
		return false;
	if (spring_member(spring)->layout == this)
		return true;
	if (!member.items.append(ILayoutItem()))
		return false;
	ILayoutItem& item = member.items.last();
	item.spring = spring;
	if (stretch >= 0.0f)
		item.stretch.heightStretch() = stretch;
	if (spring_member(spring)->layout)
		spring_member(spring)->layout->remove(spring);
	spring_member(spring)->layout = this;
	BLayout::dirty();
	return true;
}

BSpacer* BVBoxLayout::addSpacer(int height, float stretch)
{
	BSpacer* spacer = new BSpacer(0, height);
	addSpacer(spacer, stretch);
	return spacer;
}
BSpring* BVBoxLayout::addSpring(float stretch)
{
	BSpring* spring = new BSpring();
	addSpring(spring, stretch);
	return spring;
}

bool BVBoxLayout::insertWidget(int pos, BWidget* widget, float stretch)
{
	int index = member.items.find(widget);
	if (member.items.check(index))
	{
		if (index == pos)
			return true;
		ILayoutItem item = member.items[index];
		if (stretch >= 0.0f)
			item.stretch.heightStretch() = stretch;
		member.items.remove(index);
		member.items.insert(pos, item);
		BLayout::dirty();
		return true;
	}
	if (!member.items.insert(pos, ILayoutItem()))
		return false;
	ILayoutItem& item = member.items[pos];
	item.widget = widget;
	if (stretch >= 0.0f)
		item.stretch.heightStretch() = stretch;
	if (widget)
	{
		if (widget_member(widget)->upperLayout)
			widget_member(widget)->upperLayout->remove(widget);
		widget_member(widget)->upperLayout = this;
		if (layout_member(this)->host)
			layout_member(this)->host->addChild(widget);
	}
	BLayout::dirty();
	return true;
}
bool BVBoxLayout::insertLayout(int pos, BLayout* layout, float stretch)
{
	int index = member.items.find(layout);
	if (member.items.check(index))
	{
		if (index == pos)
			return true;
		ILayoutItem item = member.items[index];
		if (stretch >= 0.0f)
			item.stretch.heightStretch() = stretch;
		member.items.remove(index);
		member.items.insert(pos, item);
		BLayout::dirty();
		return true;
	}
	if (!member.items.insert(pos, ILayoutItem()))
		return false;
	ILayoutItem& item = member.items[pos];
	item.layout = layout;
	if (stretch >= 0.0f)
		item.stretch.heightStretch() = stretch;
	if (layout)
	{
		if (layout_member(layout)->parent)
			layout_member(layout)->parent->remove(layout);
		layout_member(layout)->parent = this;
		layout_member(layout)->setHost(layout_member(this)->host);
	}
	BLayout::dirty();
	return true;
}
bool BVBoxLayout::insertSpacer(int pos, BSpacer* spacer, float stretch)
{
	int index = member.items.find(spacer);
	if (member.items.check(index))
	{
		if (index == pos)
			return true;
		ILayoutItem item = member.items[index];
		if (stretch >= 0.0f)
			item.stretch.heightStretch() = stretch;
		member.items.remove(index);
		member.items.insert(pos, item);
		BLayout::dirty();
		return true;
	}
	if (!member.items.insert(pos, ILayoutItem()))
		return false;
	ILayoutItem& item = member.items[pos];
	item.spacer = spacer;
	if (stretch >= 0.0f)
		item.stretch.heightStretch() = stretch;
	if (spacer)
	{
		if (spacer_member(spacer)->layout)
			spacer_member(spacer)->layout->remove(spacer);
		spacer_member(spacer)->layout = this;
	}
	BLayout::dirty();
	return true;
}
bool BVBoxLayout::insertSpring(int pos, BSpring* spring, float stretch)
{
	int index = member.items.find(spring);
	if (member.items.check(index))
	{
		if (index == pos)
			return true;
		ILayoutItem item = member.items[index];
		if (stretch >= 0.0f)
			item.stretch.heightStretch() = stretch;
		member.items.remove(index);
		member.items.insert(pos, item);
		BLayout::dirty();
		return true;
	}
	if (!member.items.insert(pos, ILayoutItem()))
		return false;
	ILayoutItem& item = member.items[pos];
	item.spring = spring;
	if (stretch >= 0.0f)
		item.stretch.heightStretch() = stretch;
	if (spring)
	{
		if (spring_member(spring)->layout)
			spring_member(spring)->layout->remove(spring);
		spring_member(spring)->layout = this;
	}
	BLayout::dirty();
	return true;
}

BSpacer* BVBoxLayout::insertSpacer(int pos, int height, float stretch)
{
	BSpacer* spacer = new BSpacer(0, height);
	insertSpacer(pos, spacer, stretch);
	return spacer;
}
BSpring* BVBoxLayout::insertSpring(int pos, float stretch)
{
	BSpring* spring = new BSpring();
	insertSpring(pos, spring, stretch);
	return spring;
}

bool BVBoxLayout::remove(int pos)
{
	ILayoutItem& item = member.items(pos);
	if (item.widget)
		return remove(item.widget);
	else if (item.layout)
		return remove(item.layout);
	else if (item.spacer)
		return remove(item.spacer);
	else if (item.spring)
		return remove(item.spring);
	return false;
}
int BVBoxLayout::index(const BObject* object) const
{
	return member.items.find(object);
}
BRect BVBoxLayout::cellRect(int pos) const
{
	return member.items(pos).rect;
}

bool BVBoxLayout::dirty(const BObject* object)
{
	for (int i = 0; i < member.items.size(); i++)
	{
		if (member.items[i] == object)
		{
			member.items[i].dirty = true;
			BLayout::dirty();
			return true;
		}
	}
	return BLayout::dirty(object);
}
Align BVBoxLayout::align(const BObject* object) const
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.widget == object)
			return item.align;
		if (item.layout == object)
			return item.align;
		if (item.spacer == object)
			return item.align;
		if (item.spring == object)
			return item.align;
	}
	return BLayout::align(object);
}
const BRect& BVBoxLayout::area(const BObject* object) const
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.widget == object)
			return item.rect;
		if (item.layout == object)
			return item.rect;
		if (item.spacer == object)
			return item.rect;
		if (item.spring == object)
			return item.rect;
	}
	return BLayout::area(object);
}

int BVBoxLayout::count() const
{
	return member.items.size();
}
BObject* BVBoxLayout::object(int pos) const
{
	if (member.items(pos).widget)
		return member.items(pos).widget;
	else if (member.items(pos).layout)
		return member.items(pos).layout;
	else if (member.items(pos).spacer)
		return member.items(pos).spacer;
	else if (member.items(pos).spring)
		return member.items(pos).spring;
	return 0;
}
BWidget* BVBoxLayout::widget(int index) const
{
	return member.items(index).widget;
}
BLayout* BVBoxLayout::layout(int index) const
{
	return member.items(index).layout;
}
BSpacer* BVBoxLayout::spacer(int index) const
{
	return member.items(index).spacer;
}
BSpring* BVBoxLayout::spring(int index) const
{
	return member.items(index).spring;
}

BObject* BVBoxLayout::find(const BString& name) const
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.widget && item.widget->name() == name)
			return item.widget;
		if (item.spring && item.spring->name() == name)
			return item.spring;
		if (item.spacer && item.spacer->name() == name)
			return item.spacer;
		if (item.layout)
		{
			if (item.layout->name() == name)
				return item.layout;
			BObject* object = item.layout->find(name);
			if (object)
				return object;
		}
	}
	return BLayout::find(name);
}
BWidget* BVBoxLayout::findWidget(const BString& name) const
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.widget && item.widget->name() == name)
			return item.widget;
		if (item.layout)
		{
			BWidget* widget = item.layout->findWidget(name);
			if (widget)
				return widget;
		}
	}
	return BLayout::findWidget(name);
}
BLayout* BVBoxLayout::findLayout(const BString& name) const
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.layout)
		{
			if (item.layout->name() == name)
				return item.layout;
			BLayout* layout = item.layout->findLayout(name);
			if (layout)
				return layout;
		}
	}
	return BLayout::findLayout(name);
}
BSpacer* BVBoxLayout::findSpacer(const BString& name) const
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.spacer && item.spacer->name() == name)
			return item.spacer;
		if (item.layout)
		{
			BSpacer* spacer = item.layout->findSpacer(name);
			if (spacer)
				return spacer;
		}
	}
	return BLayout::findSpacer(name);
}
BSpring* BVBoxLayout::findSpring(const BString& name) const
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.spring && item.spring->name() == name)
			return item.spring;
		if (item.layout)
		{
			BSpring* spring = item.layout->findSpring(name);
			if (spring)
				return spring;
		}
	}
	return BLayout::findSpring(name);
}

bool BVBoxLayout::contain(const BWidget* widget) const
{
	if (!widget)
		return false;
	for (int i = 0; i < member.items.size(); i++)
	{
		const ILayoutItem& item = member.items[i];
		if (item.widget == widget)
			return true;
		if (item.layout && item.layout->contain(widget))
			return true;
	}
	return BLayout::contain(widget);
}
bool BVBoxLayout::contain(const BLayout* layout) const
{
	if (!layout)
		return false;
	for (int i = 0; i < member.items.size(); i++)
	{
		const ILayoutItem& item = member.items[i];
		if (item.layout == layout)
			return true;
		if (item.layout && item.layout->contain(layout))
			return true;
	}
	return BLayout::contain(layout);
}
bool BVBoxLayout::contain(const BSpacer* spacer) const
{
	if (!spacer)
		return false;
	for (int i = 0; i < member.items.size(); i++)
	{
		const ILayoutItem& item = member.items[i];
		if (item.spacer == spacer)
			return true;
		if (item.layout && item.layout->contain(spacer))
			return true;
	}
	return BLayout::contain(spacer);
}
bool BVBoxLayout::contain(const BSpring* spring) const
{
	if (!spring)
		return false;
	for (int i = 0; i < member.items.size(); i++)
	{
		const ILayoutItem& item = member.items[i];
		if (item.spring == spring)
			return true;
		if (item.layout && item.layout->contain(spring))
			return true;
	}
	return BLayout::contain(spring);
}

bool BVBoxLayout::remove(BWidget* widget)
{
	if (!widget)
		return false;
	if (widget_member(widget)->upperLayout == this)
	{
		widget_member(widget)->upperLayout = 0;
		member.items.remove(widget);
		if (BWidget* host = layout_member(this)->host)
			host->removeChild(widget);
		BLayout::dirty();
		return true;
	}
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.layout && item.layout->remove(widget))
		{
			BLayout::dirty();
			return true;
		}
	}
	return BLayout::remove(widget);
}
bool BVBoxLayout::remove(BLayout* layout)
{
	if (!layout)
		return false;
	if (layout_member(layout)->parent == this)
	{
		if (BWidget* host = this->host())
			widget_member(host)->takeLayout(layout);
		layout_member(layout)->parent = 0;
		member.items.remove(layout);
		BLayout::dirty();
		return true;
	}
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.layout && item.layout->remove(layout))
		{
			BLayout::dirty();
			return true;
		}
	}
	return BLayout::remove(layout);
}
bool BVBoxLayout::remove(BSpacer* spacer)
{
	if (!spacer)
		return false;
	if (spacer_member(spacer)->layout == this)
	{
		spacer_member(spacer)->layout = 0;
		member.items.remove(spacer);
		BLayout::dirty();
		return true;
	}
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.layout && item.layout->remove(spacer))
		{
			BLayout::dirty();
			return true;
		}
	}
	return BLayout::remove(spacer);
}
bool BVBoxLayout::remove(BSpring* spring)
{
	if (!spring)
		return false;
	if (spring_member(spring)->layout == this)
	{
		spring_member(spring)->layout = 0;
		member.items.remove(spring);
		BLayout::dirty();
		return true;
	}
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.layout && item.layout->remove(spring))
		{
			BLayout::dirty();
			return true;
		}
	}
	return BLayout::remove(spring);
}
bool BVBoxLayout::clear()
{
	if (member.items.size())
	{
		for (int i = 0; i < member.items.size(); i++)
		{
			ILayoutItem& item = member.items[i];
			if (BWidget* widget = item.widget)
			{
				widget_member(widget)->upperLayout = 0;
				if (BWidget* host = layout_member(this)->host)
					host->removeChild(widget);
			}
			if (BLayout* layout = item.layout)
			{
				layout_member(layout)->setHost(0);
			}
		}
		member.items.clear();
		BLayout::dirty();
		return true;
	}
	return BLayout::clear();
}

BSizePolicy BVBoxLayout::sizePolicy() const
{
	BSizePolicy policy = layout_member(this)->sizePolicy;
	if (policy.widthPolicy() == Policy_None)
	{
		for (int i = 0; i < member.items.size(); i++)
		{
			ILayoutItem& item = member.items[i];
			if (item.dirty)
				item.flush();
			if (item.ignored)
				continue;
			policy.widthPolicy() |= item.sizePolicy.widthPolicy();
		}
	}
	if (policy.heightPolicy() == Policy_None)
	{
		for (int i = 0; i < member.items.size(); i++)
		{
			ILayoutItem& item = member.items[i];
			if (item.dirty)
				item.flush();
			if (item.ignored)
				continue;
			policy.heightPolicy() |= item.sizePolicy.heightPolicy();
		}
	}
	return policy;
}
BSize BVBoxLayout::baseSize() const
{
	BSize size;
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.dirty)
			item.flush();
		if (item.ignored)
			continue;
		if (item.spring)
			continue;
		size.height() += item.size.height();
		size.width() = bMax(size.width(), item.size.width());
	}
	return size;
}
BSize BVBoxLayout::sizeHint() const
{
	const BMargin& margin = this->margin();
	int spacing = this->spacing();
	int maxWidth = margin.width();
	int totalHeight = 0;
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.dirty)
			item.flush();
		if (item.ignored)
			continue;
		totalHeight += item.preferSize.height() + spacing;
		maxWidth = bMax(maxWidth, margin.width() + item.preferSize.width());
	}
	totalHeight -= spacing;
	if (totalHeight < 0)
		totalHeight = 0;
	return BSize(maxWidth, totalHeight + margin.height());
}
BSize BVBoxLayout::fixedSize() const
{
	BSize fixedSize = layout_member(this)->fixedSize;
	if (fixedSize.width() == 0 || fixedSize.height() == 0)
	{
		const BMargin& margin = this->margin();
		int spacing = this->spacing();
		int fixedWidth = fixedSize.width();
		int fixedHeight = fixedSize.height();
		for (int i = 0; i < member.items.size(); i++)
		{
			ILayoutItem& item = member.items[i];
			if (item.dirty)
				item.flush();
			if (item.ignored)
				continue;
			fixedHeight += item.fixedSize.height() + spacing;
			fixedWidth = bMax(fixedWidth, item.fixedSize.width());
		}
		if (fixedSize.width() == 0)
			fixedSize.width() = fixedWidth + margin.left() + margin.right();
		if (fixedSize.height() == 0)
			fixedSize.height() = fixedHeight + margin.top() + margin.bottom();
	}
	return fixedSize;
}
BSize BVBoxLayout::minSize() const
{
	int minWidth = layout_member(this)->minSize.width();
	int minHeight = layout_member(this)->minSize.height();
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.dirty)
			item.flush();
		if (item.ignored)
			continue;

		if (item.sizePolicy.heightPolicy() == Policy_Fixed)
			minHeight += item.fixedSize.height();
		else
			minHeight += item.minSize.height();

		if (item.sizePolicy.widthPolicy() == Policy_Fixed)
			minWidth = bMax(minWidth, item.fixedSize.width());
		else
			minWidth = bMax(minWidth, item.minSize.width());
	}
	return BSize(minWidth, minHeight);
}
BSize BVBoxLayout::maxSize() const
{
	int maxWidth = layout_member(this)->maxSize.width();
	int maxHeight = layout_member(this)->maxSize.height();
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (item.dirty)
			item.flush();
		if (item.ignored)
			continue;

		if (item.sizePolicy.heightPolicy() == Policy_Fixed)
			maxHeight += item.fixedSize.height();
		else
			maxHeight += item.maxSize.height();

		if (item.sizePolicy.widthPolicy() == Policy_Fixed)
			maxWidth = bMax(maxWidth, item.fixedSize.width());
		else
			maxWidth = bMax(maxWidth, item.maxSize.width());
	}
	return BSize(maxWidth, maxHeight);
}
bool BVBoxLayout::adjust()
{
	if (!layout_member(this)->dirty)
		return false;

	member.distributeHeight();
	member.applyRects();

	layout_member(this)->dirty = false;
	if (this->checks(Signal_Adjust))
		this->emit(Signal_Adjust, layout_member(this)->rect);
	return true;
}

void BVBoxLayout::attached(BWidget* host)
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (BWidget* widget = item.widget)
			host->addChild(widget);
		if (BLayout* layout = item.layout)
			layout_member(layout)->setHost(host);
	}
}
void BVBoxLayout::detached(BWidget* host)
{
	for (int i = 0; i < member.items.size(); i++)
	{
		ILayoutItem& item = member.items[i];
		if (BWidget* widget = item.widget)
			host->removeChild(widget);
		if (BLayout* layout = item.layout)
			layout_member(layout)->setHost(0);
	}
}

void BVBoxLayout::event(const BEvent& event)
{
	if (member.splitable)
	{
		switch (event.type())
		{
		case Event_MouseEnter:
			this->mouseEnterEvent((const BMouseEvent&)event);
			return;
		case Event_MouseLeave:
			this->mouseLeaveEvent((const BMouseEvent&)event);
			return;
		case Event_MouseMove:
			this->mouseMoveEvent((const BMouseEvent&)event);
			return;
		case Event_MousePress:
			this->mousePressEvent((const BMouseEvent&)event);
			return;
		case Event_MouseRelease:
			this->mouseReleaseEvent((const BMouseEvent&)event);
			return;
		default:
			break;
		}
	}
	BLayout::event(event);
}

void BVBoxLayout::styleEvent(const BEvent& event)
{
	const BStyle* style = event.value();

	style_member(style)->assign(Value_Spacing, member.spacing);
	style_member(style)->assign(Value_HorSpacing, member.spacing);
	style_member(style)->assign(Value_Handle_Size, member.handleSize);

	BLayout::styleEvent(event);
}
void BVBoxLayout::freshEvent(const BEvent& event)
{

}
void BVBoxLayout::paintEvent(const BEvent& event)
{
	if (member.handleSize.height() > 0 && member.handleIndex >= 0)
	{
		BPainter painter(this->host());
		painter.setStyle(this->style());
		BRectf handleRect = member.handleRect(member.handleIndex);
		handleRect.top() = handleRect.center().y() - member.handleSize.height() * 0.5f;
		handleRect.bottom() = handleRect.top() + member.handleSize.height();
		State handleState = this->enabled() ? State_Normal : State_Disable;
		if (member.pressed)
			handleState |= State_Pressed;
		else
			handleState |= State_Hovered;
		if (const BImage* image = painter.image(Image_Handle, handleState))
		{
			painter.drawImage(handleRect, image);
		}
		else if (painter.setColor(Color_Handle, handleState))
		{
			painter.fillRect(handleRect);
		}
	}
}

void BVBoxLayout::mouseEnterEvent(const BMouseEvent& mouseEvent)
{
	member.handleIndex = -1;
}
void BVBoxLayout::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{
	if (member.handleIndex >= 0)
	{
		member.handleIndex = -1;
		this->host()->setCursor(Cursor_None);
		this->fresh();
	}
}

void BVBoxLayout::mousePressEvent(const BMouseEvent& mouseEvent)
{
	if (mouseEvent.button() == Button_Left)
	{
		if (member.handleIndex >= 0)
		{
			member.pressed = true;
			member.pressCenter = member.handleRect(member.handleIndex).center();
			member.dragCaches.resize(member.items.size());
			for (int i = 0; i < member.items.size(); i++)
			{
				ILayoutItem& item = member.items[i];
				member.dragCaches[i] = item.realSize;
			}
			this->fresh();
			mouseEvent.accept();
		}
	}
}
void BVBoxLayout::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{
	if (mouseEvent.button() == Button_Left)
	{
		if (member.pressed != false)
		{
			member.pressed = false;
			this->emit(Signal_SplitFinished, member.handleIndex);
			this->fresh();
			mouseEvent.accept();
		}
	}
}
void BVBoxLayout::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	if (member.pressed)
	{
		if (member.dragHandle(mouseEvent.pos()))
		{
			BWidget* host = this->host();
			widget_member(host)->procEvent(Event_Adjust);
			this->emit(Signal_Splitting, member.handleIndex);
		}
		this->fresh();
		mouseEvent.accept();
	}
	else
	{
		int handleIndex = -1;
		const BPoint& pos = mouseEvent.pos();
		for (int i = 0; i < member.items.size() - 1; i++)
		{
			BRect handleRect = member.handleRect(i);
			if (handleRect.contain(pos))
			{
				handleIndex = i;
				break;
			}
		}
		member.checkHandle(handleIndex);
		if (member.handleIndex != handleIndex)
		{
			member.handleIndex = handleIndex;
			if (member.handleIndex < 0)
				this->host()->setCursor(Cursor_None);
			else
				this->host()->setCursor(Cursor_SizeVer);
			this->fresh();
		}
		if (member.handleIndex >= 0)
		{
			mouseEvent.accept();
		}
	}
}
